/**
 * 用户模型
 */
import lodash from 'lodash';
import moment from 'moment';

import {
  EVENT_USER_AUTH_UNAVAILABLE,
  userAuthEventEmitter,
} from '@/events/user-auth';

import {
  Base64Decrypt,
} from 'utils/cipher-handlers';

import {
  ucenterAuthUserLogin,
  ucenterAuthGetUserAuthList,
  ucenterAuthGetUserInfo,
} from 'services';

const defaultState = {
  /**
   * 用户认证（包含了用户的jwt，超时等）
   *  // TODO:: 身份认证待处理
   */
  authState: {
    jwt: 'eyJhbGciOiJIUzI1NiJ9.eyJqdGkiOiIxNDMzOTk4NTc3MjQ4MDk2MjU4IiwiaWF0IjoxNjMwNzUwMDY1LCJzdWIiOiJUaGhQQmkzaE9UOWlZTVc5Q0ZCUEpnPT0iLCJpc3MiOiJYTS1VTklPTi1DTVMiLCJleHAiOjE2MzA3NTE4NjV9.5SMmkPyLQZChBToiVo1OfLORzwfg0ME49UDAobo1BT4',  // 完整的jwt字符串
    id: '1433998577248096258',   // 用户在在线教育平台的id
    iat: 0,   // jwt发布时间点
    iss: '',  // jwt颁发机构
    exp: 0,   // jwt过期时间点
  },

  /**
   * 用户权限
   */
  authorityState: {
    // 用户拥有的权限
    userOwnedAuthorities: [],
  },

  /**
   * 用户信息
   */
  userInfoState: {
    id: '', // 在线教育平台id
    name: '',   // 姓名
    avatar: '', // 头像
    birthDate: '', // 生日
    credentialNumber: '',  //证件号
    credentialType: '', // 证件类型
    gender: '', // 性别
    status: '',
    telephone: '',
    unionMemberId: '',
    unions: '',
    unit: '',
  },
};

export default {

  namespace: 'ucenter',

  state: defaultState,

  effects: {
    /**
     * 用户登录
     */
    *userLogin({ payload: { ssost } }, { call, put, select }) {

      // TODO:: 跳过身份认证
      yield put({ type: 'global/loadingStateUpdate', payload: { loadingState: false } });
      return;

      try {
        // 0、开启全局loading状态
        //  yield put({ type: 'global/loadingStateUpdate', payload: { loadingState: true } });

        // 1、登录前，把原有的存储状态重置
        // yield put({ type: 'allStateReset' });

        // 2、用SSO_ST从自己服务端获取用户token及信息
        const { data: { jwt } } = yield call(ucenterAuthUserLogin, ssost);

        // code为20000在此操作，异常在catch中
        // 3、解析jwt
        const jwtArr = lodash.split(jwt, '.');

        // const header = Base64Decrypt(jwtArr[0]);
        const payload = Base64Decrypt(jwtArr[1]);
        // const signature = jwtArr[2];
        // string 转 json
        const { jti, sub, iat, exp, iss } = JSON.parse(payload);

        // 更新相关状态，将数据存入缓存
        yield put({ type: 'authStateUpdate', payload: { jwt, id: jti, iat, iss, exp } });

        // 获取用户信息
        // 在这里调用接口，获取服务端信息，然后更新状态
        const { data: {
          id,
          name,
          avatar,
          birthDate,
          credentialNumber,
          credentialType, // 证件类型
          gender, // 性别
          status,
          telephone,
          unionMemberId,
          unions,
          unit,
        } } = yield call(ucenterAuthGetUserInfo, jwt, jti);


        // 更新用户信息
        yield put({
          type: 'userInfoStateUpdate', payload: {
            id,
            name,
            avatar,
            birthDate,
            credentialNumber,
            credentialType, // 证件类型
            gender, // 性别
            status,
            telephone,
            unionMemberId,
            unions,
            unit,
          }
        });

        // 获取用户权限
        const { data } = yield call(ucenterAuthGetUserAuthList, jwt, jti);
        yield put({ type: 'authorityStateUpdate', payload: { userOwnedAuthorities: data } });

        // 登录成功后，进入主界面
        yield put({ type: 'userAuthCheck' });
      }
      catch (error) {
        // 如果有需要特殊处理的错误，就判断code和msg，如果没有，则继续抛出给全局处理
        // 网络异常，已经拦截掉了
        const { code, msg } = error;
        // callback错误弹框后，用户点确认时的回调,重新登录
        throw { code, msg };
      }
    },

    /**
     * 检测用户的认证状态
     */
    *userAuthCheck(_, { call, put, select }) {
      try {
        // 延迟加载authState,保证authState是从缓存加载出来的
        const { authState: { jwt, exp } } = yield select(state => state.ucenter);

        // 如果前端没有jwt，则跳转到登录页面
        if (!jwt) throw { code: 40001, msg: '用户身份失效，请重新登录' };

        // jwt存在，且已过期(当前时间在过期时间之后)
        if (moment().isSameOrAfter(moment.unix(exp))) throw { code: 40001, msg: '用户身份失效，请重新登录' };

        // 全局加载-结束
        yield put({ type: 'global/loadingStateUpdate', payload: { loadingState: false } });
      }
      catch (error) {
        yield put({ type: 'userLogout' });

        // 如果有需要特殊处理的错误，就判断code和msg，如果没有，则继续抛出给全局处理
        // 网络异常，已经拦截掉了
        // const { code, msg } = error;
        // callback错误弹框后，用户点确认时的回调,重新登录
        // throw { code, msg };
      }
    },

    /**
     * 用户登出
     */
    *userLogout(_, { call, put, select }) {
      // 1、清空用户信息
      yield put({ type: 'allStateReset' });


      const { pathname, state, query } = yield select(state => state.router.location);

      // 2、计算登录成功后的回转路径
      const returnHost = process.env.host.address;
      // let returnRouter = '/home/website/main';
      let returnRouter = pathname;

      let queryString = '';

      if (!!state) {
        for (let key in state) {
          queryString += '' + key + '=' + state[key] + '&';
        }
        queryString = lodash.trimEnd(queryString, '&');
      }

      else if (!!query) {
        for (let key in query) {
          // 把本来ssost的剔除
          if (key == 'ssost') continue;
          queryString += '' + key + '=' + query[key] + '&';
        }
        queryString = lodash.trimEnd(queryString, '&');
      }

      // 返回路径
      if (!!queryString) returnRouter += '?' + queryString;

      // 3、重定向到登录界面
      userAuthEventEmitter.emit(EVENT_USER_AUTH_UNAVAILABLE, `${returnHost}${returnRouter}`);
    },

  },

  reducers: {
    /**
     * 更新authState信息
     */
    authStateUpdate(state, { payload }) {
      const { authState } = state;
      return { ...state, authState: { ...authState, ...payload } };
    },

    /**
     * 更新用户信息
     */
    userInfoStateUpdate(state, { payload }) {
      const { userInfoState } = state;
      return { ...state, userInfoState: { ...userInfoState, ...payload } };
    },

    /**
     * 权限信息
     */
    authorityStateUpdate(state, { payload }) {
      const { authorityState } = state;
      return { ...state, authorityState: { ...authorityState, ...payload } };
    },

    /**
     * 重置信息
     */
    allStateReset(state, action) {
      return defaultState;
    },

  },

  /**
   * 订阅事件源
   */
  subscriptions: {
    /**
     * 监听浏览器路由变化
     */
    setup({ dispatch, history }) {
      // 参数就是history的location参数
      // path为路由，query为请求参数{ key=value }
      history.listen(({ pathname, query }) => {


        // 1、查询字符串中，取出单点登录参数SSO_ST
        const { ssost } = query;

        // 2、如果该参数存在,则重新登录(清空原有的登录信息)      
        if (!!ssost) {
          dispatch({ type: 'global/loadingStateUpdate', payload: { loadingState: true } });
          dispatch({ type: 'userLogin', payload: { ssost } });
          return;
        }

        // TODO:: 身份认证待处理
        dispatch({ type: 'global/loadingStateUpdate', payload: { loadingState: false } });
        // TODO:: 身份认证待处理
        // // 如果该参数不存在，又没有登录信息，则跳转至单点登录，必须用定时器把该任务排后
        // dispatch({ type: 'userAuthCheck' });
      });
    },

  },

}